#-*- coding: utf-8 -*-
#===============================================================================
# IMPORTS
#===============================================================================
from __future__ import unicode_literals

from datetime import datetime, timedelta, datetime, timedelta
import os
import traceback
import urllib
import urllib2

from dateutil import parser
from django.db import models
from django.utils.timezone import utc, utc
from pytz import timezone
import pytz

from apiManager.models import *
import datetime as DT
from eve_scm import settings, debug_tools
from eve_scm.debug_tools import d_print
from eve_static.models import Invtypes, Stastations, Invnames, Invflags
import xml.etree.ElementTree as ET


DEBUG_CONTROL = True
#===========================================================================
# Fonctions de traitement de l'api. => à voir comment replacer pour fonctionner
# avec autres classes du model.
#===========================================================================

#===========================================================================
# A MODIFIER POUR CHOISIR LE TYPE D'API ONT RECUPERE
#===========================================================================
 
    
def getApiUrl(account, apiName):
    apiUrls={ 
         'EveApi' : 'https://api.eveonline.com',
         'ApiInfo' : '/account/APIKeyInfo.xml.aspx',
         'Asset List' : '/corp/AssetList.xml.aspx',
         'Account Balances' : '/corp/AccountBalance.xml.aspx',
         'Corporation Sheet' : '/corp/CorporationSheet.xml.aspx', 
         'Industry Jobs' : '/corp/IndustryJobs.xml.aspx', 
         'Market Orders' : '/corp/Market Orders.xml.aspx', 
         'StarbaseDetail':'/corp/StarbaseDetail.xml.aspx', 
         'StarbaseList' : '/corp/StarbaseList.xml.aspx', 
         'Wallet Journal' : '/corp/WalletJournal.xml.aspx', 
         'Wallet Transactions' : '/corp/WalletTransactions.xml.aspx',  
        }
    url = "{}{}?keyID={}&vCode={}".format(apiUrls.get('EveApi'), apiUrls.get(apiName), account.keyID , account.vCode)
    
    return url
    

#OK : Fonctionnel
# fonction qui recupere l'api depuis un url
def catchApi(url):
    # recupere le xml et cree un objet ElementTree xml
    try:
        xml = urllib2.urlopen(url)
        tree = ET.parse(xml)
        root = tree.getroot()
        return root
    except Exception, e:
        print traceback.format_exc()   

#OK : Fonctionnel
#POUR DEVELOPPEMENT SEULEMENT
#fonction qui recupere l'api depuis un fichier local
def catchApiFile(xmlfile):
#recupere le xml et cree un objet ElementTree xml
    try:
        tree = ET.parse(xmlfile)
        root = tree.getroot()
        return root
    except Exception, e:
        print traceback.format_exc()

#IN DEV ++ ajouter partie user (username + passeword) => à mettre ailleurs autre applic (usermanagement)
#creation d'un account avec verification du type de clé
def create_account(accountName, keyID, vCode):
    account = ApiAccount()
    account.accountName = accountName
    account.keyID = keyID
    account.vCode = vCode
    try:
        #url = "https://api.eveonline.com/account/APIKeyInfo.xml.aspx?keyID={}&vCode={}".format(account.keyID , account.vCode)
        #root = catchApi(url)
        #ATTENTION CODE EN DUR ICI !!!!!! A CHANGER HORS DEV!!!!!!!
        filePath = os.path.join(settings.MEDIA_ROOT, 'APIKeyInfo.xml')
        root = catchApiFile(filePath)
        currentTime =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(root[0].text), is_dst=None)
        cachedUntil =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(root[2].text), is_dst=None)
        result = root.find('result')
        for child in result:
            #keyAccessMask = result.get('accessMask')
            #keyType = result.get('type')
            keyType = child.attrib.get('type')
            #TO DEV : supporter aussi clé perso => autre module (RH) ? 
            if keyType == 'Corporation':
                
                #DJANGO MESSAGES !!!
                
                print'Key verification : ok'
                account.save()
                info = ApiInfo()
                #depuis la accountID != None
                info.accountID = account
                info.accessMask = child.attrib.get('accessMask')
                info.apiType = 'Corporation'
                if child.attrib.get('expire') is not None:
                    #attention si utile en date ici pas bon format
                    info.keyExpire =  child.attrib.get('expire')
                else:
                        info.keyExpire = 'Never'
                for row in result.iter('row'):
                    info.characterID = row.attrib.get('characterID')
                    info.characterName = row.attrib.get('characterName')
                    info.corporationID = row.attrib.get('corporationID')
                    info.corporationName = row.attrib.get('corporationName')
                info.save()                 
            else:
                print 'You must enter a Corporation key !'
    except Exception, e:
        print traceback.format_exc()


#OK : fonctionnel    
#creation des path pour les fichiers xml de dev    
def create_api_files_path():
    for name in ApiNames.objects.all():
        if name.fileName is not None:
            print name.fileName
            name.filePath = os.path.join(settings.MEDIA_ROOT, name.fileName)
            name.save()
    return None

#OK : fonctionnel 
#creation des urls pour un ApiAccount donné
#problème pour posDetail => argument en + itemID ??? (pour l'instant intégré à posList
def create_apiUrl(api_account):
    #account = ApiAccount.objects.get(accountID = api_account.accountID)
    for name in ApiNames.objects.all():
        api = Api()
        api.accountID = api_account
        api.apiName = name
        api.apiUrl = "{}{}?keyID={}&vCode={}".format(name.urlBase, name.urlRadical, api_account.keyID , api_account.vCode)
        #print api.apiUrl
        api.save()
    return None

#TO DO

# caclul le status d'une api en live depuis url (prob : doit faire la requête!!!) possible première fois ou refresh
# sinon faire le calcul depuis la bd
def api_metadata(root):    
    try:
        eveTimeZone = pytz.UTC
        currentTime = pytz.timezone(eveTimeZone.zone).localize(parser.parse(root[0].text), is_dst=None)
        cachedUntil = pytz.timezone(eveTimeZone.zone).localize(parser.parse(root[2].text), is_dst=None)
        print "Current time : {} , {}".format(currentTime, type(currentTime))
        print "Cached until : {} , {}".format(cachedUntil, type(cachedUntil))
        #now = DT.datetime.now()
        now = DT.datetime.utcnow().replace(tzinfo=utc)
        if cachedUntil > now :
            apiStatus = "Cached"
            print "Cached"
        else:
            apiStatus = "Cache expired!"
            print "Cache expired!"
        metadata = [currentTime, cachedUntil, apiStatus]
    except Exception, e:
        print traceback.format_exc()
    
    return metadata

#check if the api is cached or not
def api_status(account, apiName):    
    try:
        api = Api.objects.get(apiName=apiName, accountID = account)
        if api.apiStatus and api.cachedUntil is not None:
            currentTime = api.currentTime
            cachedUntil = api.cachedUntil
            now = DT.datetime.utcnow().replace(tzinfo=utc)
            if cachedUntil > now :
                api.apiStatus = "Cached"
                print "Cached"
            else:
                api.apiStatus = "Cache expired!"
                print "Cache expired!"
        #if it's first api call set times to None
        else:
            currentTime = None
            cachedUntil = None
            api.apiStatus = 'Cache expired!'
        api.save()
    except Exception, e:
        print traceback.format_exc()
        
    return api.apiStatus

#TO MODIFY => 1 fonction qui check le status dans la base sinon incorporé dans la récupération de l'api.
#SI status pas bon => lance fonction de récupération.

#refresh toutes les clés api d'un account
#source pour dev = choix entre url et file
def refresh_api_all(account, source):
    for name in ApiNames.objects.all():
        api = Api.objects.get(accountID = account.accountID, apiName = name.apiName)
        if source == 1:
            root = catchApi(api.apiUrl)
        elif source == 2:
            root = catchApiFile(name.filePath)
        else:
            print 'no source'
    #prob va retourner qu'un seul root !!! On peu pas le faire comme ça
    return root

#refresh une clé particulière d'un account
def refresh_api(account, apiname, source):
    #? test si exist api ?
    refresh_start = DT.datetime.utcnow().replace(tzinfo=utc)
    api = Api.objects.get(accountID = account, apiName = apiname)
    apiName = ApiNames.objects.get(apiName = apiname)
    if api is not None:
        if source == 1:
            root = catchApi(api.apiUrl)
        elif source == 2:
            root = catchApiFile(apiName.filePath)
        else:
            print 'no source'
    refresh_end = DT.datetime.utcnow().replace(tzinfo=utc)
    tdelta = refresh_end - refresh_start    
    print "                                                Refresh api time : {}".format(tdelta.total_seconds())
    return root

#FOR ASSET PARSER
#iter dans un noeud d'un ElementTree suivant un path (récupère les noeuds correspondants au path) et 
#retourne un dictionnaire avec pour (key) les noeuds parent et pour (valeurs) la liste des noeuds enfants (ElementTree)
def parse_subrow(node, path):
#         self.node = node
#         self.path = path
    parse_subrow_start = DT.datetime.utcnow().replace(tzinfo=utc)
    childsList = list(node.iterfind(path))
    for child in childsList:
            #print child itemID :
            print "    -------- : {} ".format(child.get('itemID'))
    #childsList = list(node.iterfind("./rowset/row"))
    #TO THINK : au lieu de node.get('itemID') pourquoi ne pas passer l'objet element (noeud complet)
    parent_map = {node.get('itemID') : childsList}
    #print parent_map
    parse_subrow_end = DT.datetime.utcnow().replace(tzinfo=utc)
    tdelta = parse_subrow_end - parse_subrow_start    
    print "                                                Subrow parsing time : {}".format(tdelta.total_seconds())
    return parent_map

#FOR ASSET PARSER
#prend un dictionnaire et explore pour chaque key (parent) les enfants (noeuds) qui correspondent à un path
#iter de boucle en boucle (doit couvrir toutes les possibles x sub-level d'un xml)
# QUEST : a-t-on besoin de garder le path en paramètre ???  => TO OPTIMISE !!
#ADD Asset counter
#avoid len() prefere .count() if possible

def parcours_map(parent_childs_Map, path, account):
    map_start = DT.datetime.utcnow().replace(tzinfo=utc)
    assetCount=0
    reflv=[]
    espace = "    "
    for cle, valeurs in parent_childs_Map.items():
        #print cle : nb subitems - subitems
        #print "{} : {} - {}".format(cle,len(valeurs), valeurs)
        for subitem in valeurs:
            assetCount+=1
            if subitem is not None:
                #subitem = enfant
                #reflv fonctionne pas correctement => faudrait le passer d'une fonction à l'autre  ou a mettre dans parse_subrow??? 
                reflv.append(1)
                #1er lv sub item
                #print nb - itemID : nb subitems - list subitems
                #print "        {} - {} : {} - {}".format( y, subitem.get('itemID'), len(list(subitem.iterfind('./rowset/row'))), list(subitem.iterfind('./rowset/row')))
                #subAsset = Asset.objects.create_asset(subitem.get('itemID'), cle , subitem.get('locationID'), subitem.get('typeID'), subitem.get('quantity'), subitem.get('flag'), subitem.get('singleton'), subitem.get('rawQuantity'))
                try: 
                    subAsset = Asset.objects.get(itemID = subitem.get('itemID'), accountID = account.accountID)
                    print "item {} already exists".format(subAsset.itemID)
                #si l'item n'existe déjà pas dans la base on cree un nouveau
                except Asset.DoesNotExist:
                    print "item does not exists"
                    subAsset = Asset()
                    subAsset.accountID = account
                    subAsset.itemID = subitem.get('itemID')
                try:
                    subAsset.parentID = Asset.objects.get(itemID = cle)
                except Asset.DoesNotExist:
                    print "subasset parentID DOES NOT EXIST"
                    subAsset.parentID = None
                
                #n'a normalement pas de locationID : prend celui du parent : to check
                if subitem.get('locationID') is None:
                    subAsset.locationID = subAsset.parentID.locationID
                else:
                    subAsset.locationID = subitem.get('locationID')
                    
                locInfos = locate_asset(subAsset.locationID)
                subAsset.locationID = locInfos[0]
                subAsset.locationStation = locInfos[1]
                subAsset.locationName = locInfos[2]
                
                subAsset.typeID = subitem.get('typeID')
                subAsset.flag = int(subitem.get('flag'))
                try:
                    assetType = retrieve_invtypes(subAsset.typeID)
                    #invFlag = retrieve_invflags(subAsset.flag)
                except Exception , err:
                    print traceback.format_exc()    
                
                subAsset.typeName = assetType.typename
                flagInfos = flag_infos(subAsset.flag, account)
                print 'FLAG INFOS : ', flagInfos
                subAsset.flagName = flagInfos[1]
                subAsset.flagText = flagInfos[0]
#                 subAsset.typeName = assetType.typename
#                 subAsset.flagName = invFlag.flagName
#                 subAsset.flagText = invFlag.flagText
                
                subAsset.quantity = subitem.get('quantity')
                
                subAsset.singleton = subitem.get('singleton')
                subAsset.rawQuantity = subitem.get('rawQuantity')
                write_bd_start = DT.datetime.utcnow().replace(tzinfo=utc)
                subAsset.save()
                write_bd_end = DT.datetime.utcnow().replace(tzinfo=utc)
                delta = write_bd_end - write_bd_start
                print delta
                #print reflv - subitems saved
                print "           sub subitem {} saved in database".format( subitem.get('itemID'))
                #Fin premier lv parents - enfants
#_------------------------------------------------------------------------------------------------------------------------------------------
                
                
                #test si les enfants ont un ou des enfants
                if len(list(subitem.iterfind('./rowset/row'))) > 1:
                    print "        sub item has child"
                    sub_map = parse_subrow(subitem, './rowset/row')
                    parcours_map(sub_map, '/rowset/row', account)
                else:
                    print "        sub item has NO child"
            else:
                print "        sub item is NONE"
    map_end = DT.datetime.utcnow().replace(tzinfo=utc)
    tdelta = map_end - map_start    
    print "                                            Parcours MAP time processing : {}".format(tdelta.total_seconds())
    return None
                
#recupere le nom de la station en foncton du locationID
def locate_asset(locationID):
    locInfos = list()
    prefix = str(locationID)[0:2]
    if prefix == 60:
        locInfos.insert(0, locationID+6000001) 
    elif prefix == 66:
        locInfos.insert(0, locationID-6000001)
    elif prefix == 67:
        locInfos.insert(0, locationID-6000000)
#     elif prefix == 00:
#         locInfos.insert(0, )
    else:
        locInfos.insert(0, locationID)    
    try:
        station = Stastations.objects.get(stationid = locInfos[0])
        locInfos.insert(1, station.stationname)
    except Stastations.DoesNotExist:
        locInfos.insert(1, None)
    try:
        locInfos.insert(2, Invnames.objects.get(itemID = locInfos[0]).itemName)
    except Invnames.DoesNotExist:
        locInfos.insert(2, None) 
    
    return locInfos

#recupere l invtypes 
def retrieve_invtypes(typeID):
    #récupère l'objet invtypes pour avoir le nom de l'item
    try:
        assetType = Invtypes.objects.get(typeid = typeID)
    except Invtypes.DoesNotExist:
        print "No type !"
        assetType = None

    return assetType

#recupere l invflag
def retrieve_invflags(flagID):
    try:
        invflag = Invflags.objects.get(flagID = flagID)
    except Invflags.DoesNotExist:
        invflag = None
        
    return invflag

def flag_infos(flagID, account):
    corpInfos = CorpSheet.objects.get(accountID = account.accountID)
    flagValue = {0 : 'No defined',
                 4 : corpInfos.divAccountKey1000,
                 116 : corpInfos.divAccountKey1001,
                 117 : corpInfos.divAccountKey1002,
                 118 : corpInfos.divAccountKey1003,
                 119 : corpInfos.divAccountKey1004,
                 120 : corpInfos.divAccountKey1005,
                 121 : corpInfos.divAccountKey1006,
                 122 : 'Strontium bay', 
                 }
    invflag = retrieve_invflags(flagID)
    print "Flag : ", flagID
    if flagID in flagValue.keys():
        flagText = flagValue[flagID]
        print "flatText - TRUE : ", flagText
    else:
        flagText = invflag.flagText
        print "flatText - False : ", flagText
    flagName = invflag.flagName
            
    return (flagText, flagName)
    
#parse le xml en fonction de l'api recupéré
#si apiName = 'all' refresh tous les api
def apiParser(account, apiName, source):
    start_time = DT.datetime.utcnow().replace(tzinfo=utc)
    print "enter apiParser at {}".format(start_time)
    
    #===========================================================================
    # Functions that implement a case switch with the dict parserfunction below...
    #===========================================================================
    #OK : fonctionnel et testé
    def corpSheet(root, account):
        print 'enter corpSheet function'
        result = root.find('result')
        try:
            corpSheet = CorpSheet.objects.get(accountID = account)
        except CorpSheet.DoesNotExist:
            corpSheet = CorpSheet()
            corpSheet.accountID = account
        
        print "Corp ID : {}".format(type(result.find('corporationID').text))
            
        corpSheet.corporationID = int(result.find('corporationID').text)
        corpSheet.corporationName = result.find('corporationName').text
        corpSheet.corpTicket = result.find('ticker').text  
        corpSheet.ceoID = int(result.find('ceoID').text)
        corpSheet.ceoName = result.find('ceoName').text
        corpSheet.stationID = int(result.find('stationID').text)  
        corpSheet.stationName = result.find('stationName').text
        corpSheet.corpDescription = result.find('description').text
        corpSheet.corpUrl = result.find('url').text  
        corpSheet.allianceID = int(result.find('allianceID').text)
        corpSheet.factionID = int(result.find('factionID').text)
        corpSheet.corpTaxe = float(result.find('taxRate').text)  
        corpSheet.memberCount = int(result.find('memberCount').text)
        corpSheet.memberLimit = int(result.find('memberLimit').text)
        corpSheet.shares = int(result.find('shares').text)
        
        #divisions
        divisions = result.find(".//rowset[@name='divisions']")
        print "divisions : {}".format(divisions)
        #corpSheet.divAccountKey1000 = result.find(".//rowset[@name='divisions']/row[@accountKey=’1000’]").attrib.get('description')
        print divisions.find(".//*[@accountKey='1000']").get('description')
        
        corpSheet.divAccountKey1000 = divisions.find(".//*[@accountKey='1000']").get('description')
        corpSheet.divAccountKey1001 = divisions.find(".//*[@accountKey='1001']").get('description')
        corpSheet.divAccountKey1002 = divisions.find(".//*[@accountKey='1002']").get('description')
        corpSheet.divAccountKey1003 = divisions.find(".//*[@accountKey='1003']").get('description')
        corpSheet.divAccountKey1004 = divisions.find(".//*[@accountKey='1004']").get('description')
        corpSheet.divAccountKey1005 = divisions.find(".//*[@accountKey='1005']").get('description')
        corpSheet.divAccountKey1006 = divisions.find(".//*[@accountKey='1006']").get('description')
        
        #wallet divisions
        wallets = result.find(".//rowset[@name='walletDivisions']") 
        print "Wallets : {}".format(wallets)
        
        print "accountKey 1000 : {}".format(wallets.find(".//*[@accountKey='1000']").get('description'))
        corpSheet.divAccountKey1000 = wallets.find(".//*[@accountKey='1000']").get('description')
        corpSheet.divAccountKey1001 = wallets.find(".//*[@accountKey='1001']").get('description')
        corpSheet.divAccountKey1002 = wallets.find(".//*[@accountKey='1002']").get('description')
        corpSheet.divAccountKey1003 = wallets.find(".//*[@accountKey='1003']").get('description')
        corpSheet.divAccountKey1004 = wallets.find(".//*[@accountKey='1004']").get('description')
        corpSheet.divAccountKey1005 = wallets.find(".//*[@accountKey='1005']").get('description')
        corpSheet.divAccountKey1006 = wallets.find(".//*[@accountKey='1006']").get('description')

        #logo infos
        item = result.find('logo')
        corpSheet.graphicID = int(item.find('graphicID').text)
        corpSheet.shape1  = int(item.find('shape1').text)
        corpSheet.shape2  = int(item.find('shape2').text)
        corpSheet.shape3  = int(item.find('shape3').text)
        corpSheet.color1  = int(item.find('color1').text)
        corpSheet.color2  = int(item.find('color2').text)
        corpSheet.color3  = int(item.find('color3').text)
        try:
            corpSheet.save()
        except Exception, e:
            print traceback.format_exc() 
        #CorpSheet.objects.all().count()
            
        return None
    
    #Ok : fonctionnel et testé (prob général timezone et datetimefields !!!)
    def walletTrans(root, account):
        print "in wallet trans fonction...."
        
        rowset = root.find('result').find('rowset')
        print "rowset : {}".format(rowset)
        for row in rowset:
            try:
                #TEST DE L'ACCOUNT AUSSI ?
                walletT = WalletTransaction.objects.get(transactionID = row.attrib.get('transactionID'))
                print "wallet trans already exists"
            except WalletTransaction.DoesNotExist:
                print "wallet trans does not exists"    
                walletT = WalletTransaction()
                walletT.transactionID = row.attrib.get('transactionID')
                
            print "trans ID : {}".format(row.attrib.get('transactionID'))
            walletT.accountID = account
            walletT.transactionDateTime = pytz.timezone(pytz.UTC.zone).localize(parser.parse(row.attrib.get('transactionDateTime')), is_dst=None)
            walletT.transactionType = row.attrib.get('transactionType')
            walletT.transactionFor = row.attrib.get('transactionFor')
            walletT.journalTransactionID = row.attrib.get('journalTransactionID')
            walletT.typeID = row.attrib.get('typeID')
            walletT.typeName = row.attrib.get('typeName')
            walletT.quantity = row.attrib.get('quantity')
            walletT.price = row.attrib.get('price')
            walletT.clientID = row.attrib.get('clientID')
            walletT.clientName = row.attrib.get('clientName')
            walletT.clientTypeID = row.attrib.get('clientTypeID')
            walletT.characterID = row.attrib.get('characterID')
            walletT.characterName = row.attrib.get('characterName')
            walletT.stationID = row.attrib.get('stationID')
            walletT.stationName = row.attrib.get('stationName')
            
            walletT.save()
        
        print "out wallet trans funct...."
        return None
    
    #OK : fonctionnel et testé (aussi prob datetime => timezone)
    def walletJour(root, account):
        
        for row in root.find('result').find('rowset'):
            try:
                #MANQUE TEST API_ACCOUNT
                walletJ = WalletJournal.objects.get(refID = row.attrib.get('refID'), accountID = account.accountID)
                print "wallet entry already exists"
            except WalletJournal.DoesNotExist:
                print "wallet entry does not exists"    
                walletJ = WalletJournal()
                walletJ.refID = row.attrib.get('refID')
                walletJ.accountID = account
                
            walletJ.date =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(row.attrib.get('date')), is_dst=None)
            walletJ.refTypeID = row.attrib.get('refTypeID')
            walletJ.ownerName1 = row.attrib.get('ownerName1')
            walletJ.ownerID1 = row.attrib.get('ownerID1')
            walletJ.ownerName2 = row.attrib.get('ownerName2')
            walletJ.ownerID2 = row.attrib.get('ownerID2')
            walletJ.argName1 = row.attrib.get('argName1')
            walletJ.argID1 = row.attrib.get('argID1')
            walletJ.amount =  row.attrib.get('amount')
            walletJ.balance = row.attrib.get('balance')
            walletJ.reason = row.attrib.get('reason')
            walletJ.owner1TypeID = row.attrib.get('owner1TypeID')
            walletJ.owner2TypeID = row.attrib.get('owner2TypeID')
            walletJ.save() 
    
    #pas implémenté pour l'instant
    def industry(root, account):
        idy = IndustryJob()
        return None
    
    #A tester....
    def balance(root, account):
        accounts = root.find('result').find(".//rowset[@name='accounts']")
        #PAS BESOIN DE LA BOUCLE => ....
        for row in accounts:
             
            try:
                #ATTENTION MANQUE L'APPARTENANCE a un ApiAccount!!!!!
                bal = AccountBalance.objects.get(accountID = account.accountID)
                debug_tools.d_print("wallet balance already exists", DEBUG_CONTROL)
            except AccountBalance.DoesNotExist:
                debug_tools.d_print("wallet balance does not exists", DEBUG_CONTROL)   
                bal = AccountBalance()
                bal.accountID = account
                
            bal.walletAccountKey1000 = accounts.find(".//*[@accountKey='1000']").attrib.get('balance')
            bal.walletAccountKey1001 = accounts.find(".//*[@accountKey='1001']").attrib.get('balance')
            bal.walletAccountKey1002 = accounts.find(".//*[@accountKey='1002']").attrib.get('balance')
            bal.walletAccountKey1003 = accounts.find(".//*[@accountKey='1003']").attrib.get('balance')
            bal.walletAccountKey1004 = accounts.find(".//*[@accountKey='1004']").attrib.get('balance')
            bal.walletAccountKey1005 = accounts.find(".//*[@accountKey='1005']").attrib.get('balance')
            bal.walletAccountKey1006 = accounts.find(".//*[@accountKey='1006']").attrib.get('balance')
            
        bal.save()
        return None

    def orders(root, account):
        marketOrders = root.find('result').find(".//rowset[@name='orders']")
        for row in marketOrders:
             
            try:
                #orderID est-il unique pour tout le jeu ou seulement pour une corp ?
                order = MarketOrders.objects.get(orderID = row.attrib.get('orderID'), accountID = account.accountID)
                print "Market order already exists"
            except MarketOrders.DoesNotExist:
                print "Market order does not exists"    
                order = MarketOrders()
                order.orderID = row.attrib.get('orderID')
                order.accountID = account
                
            order.charID = row.attrib.get('charID')
            order.stationID = row.attrib.get('stationID')
            order.volEntered = row.attrib.get('volEntered')
            order.volRemaining = row.attrib.get('volRemaining')
            order.minVolume = row.attrib.get('minVolume')
            order.orderState = row.attrib.get('orderState')
            order.typeID = row.attrib.get('typeID')
            order.range = row.attrib.get('range')
            order.accountKey = row.attrib.get('accountKey')
            order.duration = row.attrib.get('duration')
            order.escrow = row.attrib.get('escrow')
            order.price = row.attrib.get('price')
            order.bid = row.attrib.get('bid')
            order.issued =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(row.attrib.get('issued')), is_dst=None)
            order.save()
        
        
        return None
    
    #DEV version testée : ok 
    #liee à posList : ne se lance pas directement toujours avec appel de posList avant
    def posDetail(root, pos, account):
        result = root.find('result')
        generalSettings = result.find('generalSettings')
        combatSettings = result.find('combatSettings')
        fuel = result.find('.//rowset')
        
        try:
            posDetail = PosDetail.objects.get(itemID = pos.itemID, accountID = account.accountID)
            print "POS already exists"
        except PosDetail.DoesNotExist:
            print "POS does not exists"    
            posDetail = PosDetail()
            posDetail.itemID = pos
            posDetail.accountID = account
        
        print "pos detail id : {}".format(pos.itemID)
        posDetail.stateTimestamp =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(result[1].text), is_dst=None)
        posDetail.onlineTimestamp =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(result[2].text), is_dst=None)
        posDetail.state = result[0].text
        posDetail.usageFlags = generalSettings[0].text
        posDetail.delployFlags = generalSettings[1].text 
        posDetail.allowCorpMembers = generalSettings[2].text
        posDetail.allowAllyMembers = generalSettings[3].text
        posDetail.useStandingsFrom = combatSettings[0].attrib.get('ownerID')
        posDetail.onStandingDrop = combatSettings[1].attrib.get('standing')
        posDetail.onStatusDrop_enabled = combatSettings[2].attrib.get('enabled')
        posDetail.onStatusDrop_standing = combatSettings[2].attrib.get('standing')
        posDetail.onAggression = combatSettings[3].attrib.get('enabled')
        posDetail.onCorpWar = combatSettings[4].attrib.get('enabled')
        posDetail.fuel_1_ID = fuel[0].attrib.get('typeID')
        posDetail.fuel_2_ID = fuel[1].attrib.get('typeID')
        posDetail.fuel_3_ID = fuel[2].attrib.get('typeID')
        posDetail.fuel_1_qty = fuel[0].attrib.get('quantity')
        posDetail.fuel_2_qty = fuel[1].attrib.get('quantity')
        posDetail.fuel_3_qty= fuel[2].attrib.get('quantity')
        
        posDetail.save()
        
        return None
    
    #quand on lance posList cela cree les details des pos
    #DEV version testée : OK
    def posList(root, account):
        result = root.find('result')
        starbases = result.find(".//rowset[@name='starbases']")
        print "starbases : {}".format(starbases)
        for row in starbases:
            print "row : {}".format(row.attrib.get('itemID'))
            try:
                posList = PosList.objects.get(itemID = row.attrib.get('itemID'), accountID = account.accountID)
                print "POS list already exists"
            except PosList.DoesNotExist:
                print "POS List does not exists"    
                posList = PosList()
                posList.itemID = row.attrib.get('itemID')
                posList.accountID = account
                
            print "pos id : {}".format(row.attrib.get('itemID'))
            posList.typeID = row.attrib.get('typeID')
            posList.locationID = row.attrib.get('locationID')
            posList.moonID = row.attrib.get('moonID')
            posList.state = row.attrib.get('state')
            posList.stateTimestamp =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(row.attrib.get('stateTimestamp')), is_dst=None)
            posList.onlineTimestamp =  pytz.timezone(pytz.UTC.zone).localize(parser.parse(row.attrib.get('onlineTimestamp')), is_dst=None)
            posList.standingOwnerID = row.attrib.get('standingOwnerID')
            
            posList.save()
        
        for pos in PosList.objects.all():
            name = ApiNames.objects.get(apiName = 'StarbaseDetail')
            url = "{}{}?keyID={}&vCode={}&itemID={}".format(name.urlBase, name.urlRadical, account.keyID , account.vCode, pos.itemID)   
            print "pos detail url : {}".format(url)
            #root = catchApi(url)
            #FOR DEV
            root = refresh_api(account, 'StarbaseDetail', 2)
            posDetail(root, pos, account)
                        
        return None
    
    #TO INTEGRATE!!!!
    #===========================================================================
    # TO DO => remplacer si ça marche les path en dur avec le path var
    #===========================================================================
    # fonction qui parcourt tous les noeuds avec comme tag "sutbag" contenus dans "node" dont les parents sont des noeuds qui ont un attribut "attribute" qui vaut "attributeValue"
    #récupère les premiers noeud d'un ElementTree correspondant à un path (ici stations/primary containers)
    #node = à root du xml, path = tous les row(tag) qui possèdent l'attribut "locationID"
    
    def assetList(root, account):
        assetListstart = DT.datetime.utcnow().replace(tzinfo=utc)
        assetCount=0
        result = root.find('result')
        
        print "result : {}".format(result)
        #rowCount=0
        #self.node = node
        control= True
        #ça c'est juste! ça prendra que les premiers noeuds!
        #node.iterfind(".//*[@name='assets']/row") => tous les noeud row qui sont enfants de noeuds ayant comme attribut "name" = "assets" => Ok 1 seul niveau donc ça marche   
        #A modifier pour prendre les row qui possèdent l'attribut "locationID" (plus simple) => récupère toutes les stations / conteneurs primaires
        
        #efface tous les objets dans la base
        #Asset.objects.all().delete()
        Asset.objects.filter(accountID = account.accountID).delete()
        # TO MODIFY : root /result pas bon pour iterer ici
        try:
            if result is not None:
                #path = ".//{0}[@{1}]".format(tag, attributeName)
                #selection tous les premiers noeuds (stations, qui possèdent un locationID)
                path = ".//row[@locationID]"
                rows = result.iterfind(path)
                print "rows : {}".format(rows)
                print "Nombre de row : ", len(list(result.findall(path)))
                while control:
                    try:
                        #a t on tj besoin de cette condition ( test déjà fait plus haut)
                        if rows is not None:
                            assetCount+=1
                            #rowCount += 1
                            #print "                    ", y , "- ROW COUNT : ", rowCount 
                            #parcours l'iterateur d'un cran de plus (passe à l'element suivant)
                            element = rows.next()
                            if element is not None:
                                #print nb - Item : itemID :
                                #print "{} - Item : {} :".format(y, element.get('itemID'))
                                try:
                                    #si l'item existe déjà on le met à jours
                                    asset = Asset.objects.get(itemID = element.get('itemID'), accountID = account.accountID)
                                    print "item {} already exists".format(asset.itemID)
                                #si l'item n'existe pas on cree un nouveau
                                except Asset.DoesNotExist:
                                    print "item does not exists"
                                    asset = Asset()
                                    asset.accountID = account
                                    asset.itemID = element.get('itemID')
                                    
                                #TO CHECK!
                                #ce niveau ne devrait pas avoir de parentID
                                asset.parentID = None
                                
                                asset.flag = int(element.get('flag'))
                                print "Flag type : ", type(asset.flag)
                                asset.singleton = element.get('singleton')
                                asset.rawQuantity = element.get('rawQuantity')
                                
                                if element.get('locationID') is None:
                                    asset.locationID = 0000
                                else:
                                    asset.locationID = element.get('locationID')
                                
                                locInfos = locate_asset(asset.locationID)
                                asset.locationID = locInfos[0]
                                asset.locationStation = locInfos[1]
                                asset.locationName = locInfos[2]
                                
                                
                                asset.typeID = element.get('typeID')
                                #récupère l'objet invtypes et invflag pour avoir le nom de l'item
                                
                                try:
                                    assetType = retrieve_invtypes(asset.typeID)
#                                     invFlag = retrieve_invflags(asset.flag)
                                except Exception , err:
                                    print traceback.format_exc()
                                
                                asset.typeName = assetType.typename
                                flagInfos = flag_infos(asset.flag, account)
                                print 'FLAG INFOS : ', flagInfos
                                asset.flagName = flagInfos[1]
                                asset.flagText = flagInfos[0]
                                asset.quantity = element.get('quantity')
                                
                                
                                asset.save()
                                #asset = Asset.objects.create_asset(element.get('itemID'), node.get('itemID'), element.get('locationID'), element.get('typeID'), element.get('quantity'), element.get('flag'), element.get('singleton'), element.get('rawQuantity'))
                                print "Primary Asset {} saved in database".format(element.get('itemID'))
                                
                                #test si le noeud a des enfants
                                if len(list(element.iter('row'))) > 1:
                                    print"subitem has child :"
                                    #add assetCount outside parent_map
                                    parent_map = parse_subrow(element, './rowset/row')
                                    #print "Map : ", parent_map
                                    parcours_map(parent_map, './rowset/row', account)
                                else:
                                    print " subitem has no child"
                            else:
                                print "element is NONE"
                    except StopIteration:
                        print "Stop iteration : no more element"
                        control = False
                    #metaList = toCorpItem(account)       
        except Exception , err:
                print traceback.format_exc()
        assetListend = DT.datetime.utcnow().replace(tzinfo=utc)
        tdelta = assetListend - assetListstart    
        print "                                                Asset List time processing : {}".format(tdelta.total_seconds())
        return None
    
    def toCorpItem(account):
        start = DT.datetime.utcnow().replace(tzinfo=utc)
        metaList = {}
        assetDict={}
        parentDict={}
#         try:
#             assetList = Asset.objects.filter(accountID = account.accountID)
#             #efface les items deja presents
#             corpItems = CorpItem.objects.filter(accountID = account.accountID).delete()
#         except Exception, err:
#             print traceback.format_exc()
#             
#         for asset in assetList:
#             #repère pour le nombre de passe de la boucle
#             i = 0
#             #var déclaration
#             assetAttributes = {}
#             childsDict = {}
#             childList = []
#             primary_asset =[]
#             
#             #cree une nouvelle instance du modele CoprItem
#             item = CorpItem()
#             #assign les variables semblables (TO MODIFY: CorpItem subcalss of Asset (foreignkey don't work))
#             item.accountID = account
#             item.itemID = asset.itemID
#             #item.parentID = asset.parentID
#             #item.locationID = asset.locationID
#             item.typeID = asset.typeID
#             item.flagID = asset.flag
#             item.quantity = asset.quantity
#             #TO implement meening
#             item.singleton = asset.singleton
#             item.rawQuantity = asset.rawQuantity
#             item.level = asset.level
#             
#             #assign les nouvelles variables (id => text)
#             if item.parentID is None:
#                 item.parentName = "No parent"
#             else:
#                 item.parentName = "Parent name"
#             
#         
# #             for subasset in assetList:
# #                 if subasset.parentID == asset.itemID:
# #                     childList.append(subasset.itemID) 
# #                 else:
# #                     pass
#             
#             #récupère l'objet invtypes et invflag pour avoir le nom de l'item
#             try:
#                 assetType = retrieve_invtypes(asset.typeID)
#                 invFlag = retrieve_invflags(asset.flag)
#             except Exception , err:
#                 print traceback.format_exc()    
#             
#             item.typeName = assetType.typename
#             item.flagName = invFlag.flagName
#             item.flagText = invFlag.flagText
#               
#             #==================================================================
#             # item location attributions
#             #==================================================================
#             if asset.locationID is not None:
#                 locInfos = locate_asset(asset.locationID)
#                 item.locationID = locInfos[0]
#                 item.locationStation = locInfos[1]
#                 item.locationName = locInfos[2]
#             else:
#                 item.locationID = None
#                 item.locationStation = "No station"
#                 item.locationName = "No name"
#             
#             item.save() 
# #         assetAttributes['childs'] = childList
# #         assetDict[asset] = assetAttributes
#             i+=1
        
        end = DT.datetime.utcnow().replace(tzinfo=utc)
        delta = end - start
        delta = delta.total_seconds()
        metaList['delta'] = delta
        assetDict['delta'] = delta
        
        return metaList
            
    # dict qui map les choix d'un switch avec la fonction que l'on veut executer en fonction du choix.     
    
    
    parserFunctions = { 'Asset List' : assetList , 'Account Balances' : balance, 'Corporation Sheet' : corpSheet, 'Industry Jobs' : industry, 
                     'Market Orders' : orders, 'StarbaseDetail': posDetail, 'StarbaseList' : posList, 'Wallet Journal' : walletJour, 
                     'Wallet Transactions' : walletTrans, 'To CorpItem' : toCorpItem, 
                     } 
    
    try:
        print "apiName : {} ".format( apiName) 
        if apiName == 'all':
            for name, function in parserFunctions.items():
                if api_status(account, name) == 'Cache expired!':
                    root = refresh_api_all(account, name, source)
                    function(root, account)
                    metadata = api_metadata(root)
                    api = Api.objects.get(accountID = account, apiName = name)
                    api.currentTime = metadata[0]
                    api.cachedUntil = metadata[1]
                    api.apiStatus = metadata[2]
                    api.save()
                else:
                    print "The {} data are cached".format(name)
        elif apiName == 'To CorpItem':
            parserFunctions[apiName](account)
            
        
        else:
            #à récupérer dans la base ? 
            print "test api_status = {}".format(api_status(account, apiName))
            if api_status(account, apiName) == u'Cache expired!':
                root = refresh_api(account, apiName, source)
                metadata = api_metadata(root)
                api = Api.objects.get(accountID = account, apiName = apiName)
                api.currentTime = metadata[0]
                api.cachedUntil = metadata[1]
                api.apiStatus = metadata[2]
                api.save()
                print "api {} status : {}".format(apiName, api.apiStatus)
                parserFunctions[apiName](root, account)
            else:
                print "The {} data are cached".format(apiName)
            
    except Exception, e:
        print traceback.format_exc() 
     
    
    end_time = DT.datetime.utcnow().replace(tzinfo=utc)
    tdelta = end_time - start_time    
    print "total refresh done in {} seconds".format(tdelta.total_seconds())
